package tcpClient

import (
	"errors"
	"fmt"
	"net"
	"sync"
	"time"

	"github.com/RuiGuangServer/config"
	"github.com/RuiGuangServer/logs"
)

// HandlerFunc 定义消息处理函数类型
type HandlerFunc func(data []byte, logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error

// MessageHandler 消息处理器接口
type MessageHandler interface {
	HandleMessage(data []byte, logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error
}

// TCPClient TCP客户端结构
type TCPClient struct {
	addr           string
	conn           net.Conn
	handler        HandlerFunc
	messageHandler MessageHandler
	reconnect      bool
	heartbeatMsg   []byte
	heartbeatInt   time.Duration
	stopChan       chan struct{}
	wg             sync.WaitGroup
	mutex          sync.Mutex
	isRunning      bool
	readTimeout    time.Duration
	writeTimeout   time.Duration
	bufferPool     sync.Pool
	// 新增心跳超时相关字段
	lastHeartbeat    time.Time
	heartbeatTimeout time.Duration
	heartbeatMutex   sync.RWMutex
}

// NewTCPClient 创建新的TCP客户端
func NewTCPClient(addr string, handler HandlerFunc, reconnect bool) *TCPClient {
	client := &TCPClient{
		addr:             addr,
		handler:          handler,
		reconnect:        reconnect,
		stopChan:         make(chan struct{}),
		readTimeout:      30 * time.Second,
		writeTimeout:     10 * time.Second,
		heartbeatTimeout: 90 * time.Second, // 默认90秒超时
		lastHeartbeat:    time.Now(),
	}
	client.bufferPool.New = func() any {
		buf := make([]byte, 4096)
		return &buf
	}
	return client
}

// SetTimeouts 设置读写超时
func (c *TCPClient) SetTimeouts(readTimeout, writeTimeout time.Duration) {
	c.readTimeout = readTimeout
	c.writeTimeout = writeTimeout
}

// SetHeartbeat 设置心跳消息和间隔
func (c *TCPClient) SetHeartbeat(msg []byte, interval time.Duration) {
	c.heartbeatMsg = msg
	c.heartbeatInt = interval
}

// SetHeartbeatTimeout 设置心跳超时时间
func (c *TCPClient) SetHeartbeatTimeout(timeout time.Duration) {
	c.heartbeatMutex.Lock()
	defer c.heartbeatMutex.Unlock()
	c.heartbeatTimeout = timeout
}

// UpdateLastHeartbeat 更新最后心跳时间
func (c *TCPClient) UpdateLastHeartbeat() {
	c.heartbeatMutex.Lock()
	defer c.heartbeatMutex.Unlock()
	c.lastHeartbeat = time.Now()
}

// GetLastHeartbeat 获取最后心跳时间
func (c *TCPClient) GetLastHeartbeat() time.Time {
	c.heartbeatMutex.RLock()
	defer c.heartbeatMutex.RUnlock()
	return c.lastHeartbeat
}

// IsHeartbeatTimeout 检查心跳是否超时
func (c *TCPClient) IsHeartbeatTimeout() bool {
	c.heartbeatMutex.RLock()
	defer c.heartbeatMutex.RUnlock()

	if c.heartbeatTimeout == 0 {
		return false
	}

	return time.Since(c.lastHeartbeat) > c.heartbeatTimeout
}

// Start 启动TCP客户端
func (c *TCPClient) Start(logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if c.isRunning {
		return errors.New("client is already running")
	}

	c.isRunning = true
	c.wg.Add(1)
	go c.run(logger, dataer)

	return nil
}

// Stop 停止TCP客户端
func (c *TCPClient) Stop() {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if !c.isRunning {
		return
	}

	close(c.stopChan)
	if c.conn != nil {
		_ = c.conn.Close()
	}
	c.wg.Wait()
	c.isRunning = false
}

func (c *TCPClient) run(logger *logs.AsyncLogger, dataer *logs.AsyncLogger) {
	defer c.wg.Done()

	// 启动心跳超时监控
	if c.heartbeatInt > 0 {
		c.wg.Add(1)
		go c.heartbeatMonitor(logger)
	}

	for {
		select {
		case <-c.stopChan:
			return
		default:
			// fmt.Printf("tcp Connection\n")
			err := c.connectAndServe(logger, dataer)
			if err != nil {
				logger.Error("Connection error: %v", err)
			}

			if !c.reconnect {
				return
			}

			logger.Info("Reconnecting in 5 seconds...")
			time.Sleep(5 * time.Second)
		}
	}
}

// heartbeatMonitor 心跳超时监控
func (c *TCPClient) heartbeatMonitor(logger *logs.AsyncLogger) {
	defer c.wg.Done()

	ticker := time.NewTicker(time.Duration(config.Config.ClientHB) * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-c.stopChan:
			return
		case <-ticker.C:
			if c.IsHeartbeatTimeout() {
				logger.Warn("Heartbeat timeout detected, closing connection for reconnect")
				c.mutex.Lock()
				if c.conn != nil {
					c.conn.Close() // 关闭连接触发重连
				}
				c.mutex.Unlock()
			}
		}
	}
}

func (c *TCPClient) connectAndServe(logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error {
	conn, err := net.Dial("tcp", c.addr)
	if err != nil {
		return fmt.Errorf("failed to connect to server: %v", err)
	}

	c.mutex.Lock()
	c.conn = conn
	c.mutex.Unlock()

	// 重置心跳时间
	c.UpdateLastHeartbeat()

	defer func() {
		c.mutex.Lock()
		c.conn = nil
		c.mutex.Unlock()
		conn.Close()
	}()

	logger.Info("Connected to server: %s", c.addr)

	// 启动心跳协程
	if c.heartbeatMsg != nil && c.heartbeatInt > 0 {
		c.wg.Add(1)
		go c.heartbeat(logger)
	}

	// 启动读写循环
	return c.readWriteLoop(logger, dataer)
}

func (c *TCPClient) readWriteLoop(logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error {
	readChan := make(chan []byte, 10)
	errChan := make(chan error, 1)

	// 启动读取循环
	go c.readLoop(readChan, errChan, logger)

	for {
		select {
		case data := <-readChan:
			if len(data) > 0 {
				if err := c.handleIncomingData(data, logger, dataer); err != nil {
					logger.Error("Failed to handle incoming data: %v", err)
					return err
				}
			}

		case err := <-errChan:
			if err != nil {
				logger.Error("Read error: %v", err)
				return err
			}

		case <-c.stopChan:
			return nil
		}
	}
}

func (c *TCPClient) readLoop(readChan chan<- []byte, errChan chan<- error, logger *logs.AsyncLogger) {
	defer close(readChan)
	defer close(errChan)

	for {
		select {
		case <-c.stopChan:
			return
		default:
			data, err := c.readData()
			if err != nil {
				if !errors.Is(err, net.ErrClosed) {
					logger.Debug("Read error: %v", err)
					errChan <- err
				}
				return
			}
			if len(data) > 0 {
				select {
				case readChan <- data:
				case <-c.stopChan:
					return
				}
			}
		}
	}
}

func (c *TCPClient) readData() ([]byte, error) {
	c.mutex.Lock()
	conn := c.conn
	c.mutex.Unlock()

	if conn == nil {
		return nil, net.ErrClosed
	}

	// 设置读取超时
	if err := conn.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
		return nil, err
	}

	bufPtr := c.bufferPool.Get().(*[]byte)
	defer c.bufferPool.Put(bufPtr)

	n, err := conn.Read(*bufPtr)
	if err != nil {
		return nil, err
	}

	if n == 0 {
		return nil, nil
	}

	data := make([]byte, n)
	copy(data, (*bufPtr)[:n])
	return data, nil
}

func (c *TCPClient) handleIncomingData(data []byte, logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error {
	if c.handler != nil {
		err := c.handler(data, logger, dataer)
		if err != nil {
			logger.Error("Handler error: %v", err)
			// 不返回错误，继续处理后续数据
		}
		return nil
	}
	if c.messageHandler != nil {
		err := c.messageHandler.HandleMessage(data, logger, dataer)
		if err != nil {
			logger.Error("Message handler error: %v", err)
			// 不返回错误，继续处理后续数据
		}
		return nil
	}
	return errors.New("no message handler configured")
}

func (c *TCPClient) heartbeat(logger *logs.AsyncLogger) {
	defer c.wg.Done()

	ticker := time.NewTicker(c.heartbeatInt)
	defer ticker.Stop()

	for {
		select {
		case <-c.stopChan:
			return
		case <-ticker.C:
			if err := c.SendMessage(c.heartbeatMsg); err != nil {
				logger.Error("Failed to send heartbeat: %v", err)
				return
			}
			logger.Debug("Heartbeat sent")
		}
	}
}

// SendMessage 发送消息
func (c *TCPClient) SendMessage(data []byte) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if c.conn == nil {
		return errors.New("connection not established")
	}

	// 设置写入超时
	if err := c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {
		return err
	}
	// fmt.Printf("data %v\n", data)
	_, err := c.conn.Write(data)
	return err
}

// IsConnected 检查是否连接
func (c *TCPClient) IsConnected() bool {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	return c.conn != nil
}

// GetConnection 获取当前连接（谨慎使用）
func (c *TCPClient) GetConnection() net.Conn {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	return c.conn
}
